package com.cg.service;

import com.cg.config.Result;
import com.cg.entity.Order;
import com.cg.entity.Stock;
import com.cg.mapper.OrderMapper;
import com.cg.mapper.StockMapper;
import com.cg.mapper.UserMapper;
import com.cg.utils.RedisIdWorker;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
@Service
@RequiredArgsConstructor
public class PurchaseService {

    private final UserMapper userMapper;

    private final OrderMapper orderMapper;

    private final StockMapper stockMapper;

    private final RedissonClient redissonClient;

    private final static String PRE_KEY = "lock:order-";

    private final StringRedisTemplate stringRedisTemplate;

    private final static DefaultRedisScript<Long> redisScript;

    private final RedisIdWorker redisIdWorker;

    private BlockingQueue<Order> blockingQueue = new ArrayBlockingQueue<>(1024 * 1024);

    private static final ExecutorService executorService = Executors.newSingleThreadExecutor();

    @PostConstruct
    public void init() {
        executorService.execute(new OrderExecutor());
    }

    class OrderExecutor implements Runnable {

        @SneakyThrows
        @Override
        public void run() {
            while (true) {
                //获取阻塞队列中的订单信息
                Order order = blockingQueue.take();
                //创建订单
                createOrder(order);
            }
        }
    }

    private void createOrder(Order order) {
        RLock lock = redissonClient.getLock(PRE_KEY + order.getUserId());
        boolean isLock = lock.tryLock();

        if (!isLock) {
            log.info("不允许重复下单");
        }
        try {
            //减去库存
            Stock stock = stockMapper.selectById(order.getStockId());
            stock.setCount(stock.getCount() - 1);
            stockMapper.updateById(stock);

            order.setCommodityName(stock.getCommodityName());
            orderMapper.insert(order);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    static {
        redisScript = new DefaultRedisScript<>();
        redisScript.setLocation(new ClassPathResource("seckill.lua"));
        redisScript.setResultType(Long.class);
    }

    @Transactional
    public Result doPurchase(Integer userId, Long stockId) {
        // 执行lua脚本
        Long execute = stringRedisTemplate.execute(redisScript, Collections.emptyList(), stockId.toString(), userId.toString());
        if (execute != 0) {
            return execute == 1 ? Result.fail("库存不足") : Result.fail("不能重复下单");
        }
        //为0时代表下单无异常，将下单信息放入阻塞队列中
        Order build = Order.builder()
                .userId(userId)
                .stockId(stockId)
                .build();
        blockingQueue.add(build);


        return Result.success();

    }


//    @Transactional
//    public Result doPurchase(Integer userId, Integer stockId) {
//
//        RLock lock = redissonClient.getLock(PRE_KEY + userId);
//        boolean isLock = lock.tryLock();
//
//        if (!isLock) {
//            return Result.fail("不允许重复下单");
//        }
//        //查询当前用户是否存在
//        try {
//            User user = userMapper.selectById(userId);
//            if (Objects.nonNull(user)) {
//                //减去库存
//                Stock stock = stockMapper.selectById(stockId);
//                stock.setCount(stock.getCount() - 1);
//                stockMapper.updateById(stock);
//
//                //生成订单
//                Order build = Order.builder()
//                        .userId(userId)
//                        .commodityName(stock.getCommodityName())
//                        .build();
//                orderMapper.insert(build);
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            lock.unlock();
//        }
//        return Result.success();
//

//    }
}
